#define DEBUG_AGENT

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

namespace WeiboBulletin
{
    using WeiboBulletin.Model;
    using UpdateTileAgent;
    using Microsoft.Phone.Scheduler;
    using Microsoft.Phone.Notification;
    
    public partial class MainPage : PhoneApplicationPage
    {
        private bool loaded = false;
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            //// check if application tile is pinned to Start.
            //if (Microsoft.Phone.Shell.ShellTile.ActiveTiles.Count() == 0)
            //{
            //    MessageBox.Show("Please pin this app on your start screen firstly.", "Tip", MessageBoxButton.OK);
            //    this.NavigationService.GoBack();
            //}           

            Setting setting = Setting.GetCurrentAppSetting();

            if (setting == null || setting.UserID == null)
            {
                buttonChangeAccount.Content = "Set Account";
            }
            else
            {
                buttonChangeAccount.Content = "Change Account";
            }
            
            foreach (var item in listPickerUpdateInterval.Items)
            {
                if ((string)(item as ListPickerItem).Tag == setting.UpdateIntervalInMinutesInWifi.ToString())
                {
                    listPickerUpdateInterval.SelectedItem = item;
                    break;
                }
            }

            setting.UpdateIntervalInMinutesInWifi = int.Parse( (string)(listPickerUpdateInterval.SelectedItem as ListPickerItem).Tag);
            Setting.SetCurrentAppSetting(setting);

            loaded = true;
        }

        private void buttonChangeAccount_Click(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigate(new Uri(@"/Page/LoginPage.xaml", UriKind.Relative));
        }

        private void ScheduleTileUpdateTask(int initialIntervalInMinutes)
        {
            var periodicTask = ScheduledActionService.Find(ScheduledAgent.AgentName) as PeriodicTask;
            if (periodicTask != null)
            {
                if (periodicTask.IsEnabled && periodicTask.LastScheduledTime> DateTime.Now 
                    && periodicTask.LastScheduledTime < DateTime.Now.AddMinutes(initialIntervalInMinutes))
                {
                    return;
                }

                RemoveAgent(ScheduledAgent.AgentName);
            }

            periodicTask = new PeriodicTask(ScheduledAgent.AgentName);
            periodicTask.Description = ScheduledAgent.AgentDescription;

            try
            {
                ScheduledActionService.Add(periodicTask);

                // If debugging is enabled, use LaunchForTest to launch the agent in one minute.
#if(DEBUG_AGENT)
                ScheduledActionService.LaunchForTest(ScheduledAgent.AgentName, TimeSpan.FromMinutes(initialIntervalInMinutes));
#endif
            }
            catch (InvalidOperationException exception)
            {
                if (exception.Message.Contains("BNS Error: The action is disabled"))
                {
                    MessageBox.Show("Background agents for this application have been disabled by the user.");
                    listPickerUpdateInterval.SelectedIndex = 0;
                }
            }            
        }

        private void listPickerUpdateInterval_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (listPickerUpdateInterval == null || loaded==false)
            {
                return;
            }

            var selected = listPickerUpdateInterval.SelectedItem as ListPickerItem;

            if (selected != null)
            { 
                Setting setting = Setting.GetCurrentAppSetting();
                setting.UpdateIntervalInMinutesInWifi = int.Parse((string)selected.Tag);
                Setting.SetCurrentAppSetting(setting);

                if (setting.UpdateIntervalInMinutesInWifi != 0)
                {
                    //this.ScheduleTileUpdateTask(setting.UpdateIntervalInMinutesInWifi);
                    UpdateSubscription();
                }
            }
            else
            {
                RemoveAgent(ScheduledAgent.AgentName);
            }
        }

        private void RemoveAgent(string name)
        {
            try
            {
                ScheduledActionService.Remove(name);
            }
            catch (Exception)
            {
            }
        }

        private void UpdateSubscription()
        {            
            HttpNotificationChannel pushChannel;
            const string channelName = "WeiboPushServiceChannel";

            pushChannel = HttpNotificationChannel.Find(channelName);
            // for debug
            if (pushChannel != null)
            {
                pushChannel.Close();
                pushChannel = null;
            }

            if (pushChannel == null)
            {
                pushChannel = new HttpNotificationChannel(channelName);
                pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
                pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
                pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotification);
                pushChannel.Open();
                System.Collections.ObjectModel.Collection<Uri> c = new System.Collections.ObjectModel.Collection<Uri>();
                c.Add(new Uri("http://tp1.sinaimg.cn/"));
                c.Add(new Uri("http://tp2.sinaimg.cn/"));
                c.Add(new Uri("http://tp3.sinaimg.cn/"));
                c.Add(new Uri("http://tp4.sinaimg.cn/"));
                c.Add(new Uri("http://tp5.sinaimg.cn/"));
                c.Add(new Uri("http://ww1.sinaimg.cn/"));
                c.Add(new Uri("http://ww2.sinaimg.cn/"));
                c.Add(new Uri("http://ww3.sinaimg.cn/"));
                c.Add(new Uri("http://ww4.sinaimg.cn/"));
                c.Add(new Uri("http://ww5.sinaimg.cn/"));
                c.Add(new Uri("http://sinaimg.cn/"));
                c.Add(new Uri("http://localhost:1859/"));
                c.Add(new Uri("http://localhost/"));
                pushChannel.BindToShellTile(c);
            }
            else
            {
                pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
                pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
                pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotification);

                // Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
                System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
                RegisterClient(pushChannel.ChannelUri.AbsoluteUri);
            }            
        }

        private void RegisterClient(string channelUri)
        {
            Setting setting = Setting.GetCurrentAppSetting();
            PushServiceReference.PushServiceClient client = new PushServiceReference.PushServiceClient();
            var userProfile = new PushServiceReference.UserProfile();
            userProfile.UserID = setting.UserID;
            userProfile.AccessToken = setting.AccessToken;
            userProfile.AccessSecret = setting.AccessSecret;
            userProfile.UpdateIntervalInMinutes = (uint)setting.UpdateIntervalInMinutesInWifi;
            userProfile.PushChannel = channelUri;
            client.RegisterAsync(userProfile);
        }

        /// <summary>
        /// Event handler for when the Push Channel Uri changes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            Dispatcher.BeginInvoke(() =>
            {
                // Display the new URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
                System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());
                MessageBox.Show(String.Format("Channel Uri is {0}",
                    e.ChannelUri.ToString()));
            });

            RegisterClient(e.ChannelUri.AbsoluteUri);
        }

        /// <summary>
        /// Event handler for when a Push Notification error occurs.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
        {
            // Error handling logic for your particular application would be here.
            Dispatcher.BeginInvoke(() =>
                MessageBox.Show(String.Format("A push notification {0} error occurred.  {1} ({2}) {3}",
                    e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData))
                    );
        }

        void PushChannel_HttpNotification(object sender, HttpNotificationEventArgs e)
        {
        }

    }
}